/*
   FieldVis - A Tool for Visualizing Astrophysical Magnetohydrodynamic Flow
   
   Copyright (C) 2006 - 2008     FieldVis Development Team
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
  
   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
   File     : Streamtube.h
   Author   : Blayne Field
   
   Purpose  : Definition header file for the Streamtube class.  This class
              holds all of the relevant information for creating a streamtube.
*/

#ifndef STREAMTUBE_H
#define STREAMTUBE_H

#include <cmath>
#include <iostream>

#include <GL/gl.h>

#include "Point.h"
#include "Vector3D.h"
#include "Field.h"
#include "Integrator.h"
#include "StreamlinePath.h"
#include "ColorMap.h"
#include "Texture.h"

const int   DEFAULT_TUBE_SIDES(12);
const float DEFAULT_TUBE_RADIUS(0.01);
const float DEFAULT_TUBE_RED(1);
const float DEFAULT_TUBE_GREEN(0);
const float DEFAULT_TUBE_BLUE(0);
const float DEFAULT_CAP_LENGTH(0.04);


class Streamtube
{
public:

   Streamtube(VectorField *vfield, Point seed, int maxPoints, bool BothDirections,
              float minThreshold, int ID, ColorMap *pColorMap, int NumSides, Texture *pTex,
              bool proportionalTexture, ScalarField *helicity, float Radius);
   ~Streamtube();

   void DrawStreamtube(GLenum drawMode);
   void PutTubeAt(Point seedPoint);

   // accessors
   int GetPointCount() const           { return(points);}
   int GetSides() const                { return(sides);}
   int GetPathStartPointIndex()        { return(sline.GetStartPointIndex());}
   Point GetPathCoordinates(int index) { return(sline.GetCoordinates()[index]);}

   // disallow copy contructor and assignment operator.... for now at least
protected:
   Streamtube &operator=(const Streamtube & toCopy);
   Streamtube(const Streamtube & toCopy);

private:

   VectorField *vectorField;
   int MaxIntegrationPoints;
   bool bothDirections;
   float MinimumThreshold;
   
   int pointArraySize;        // size of the GLfloat array that we want.
   int pointArrayAllocated;   // size of the GLfloat array that has been allocated.
   int indexArraySize;        // size of the GLint array that we want.
   int indexArrayAllocated;   // size of the GLint array that has been allocated.
   
   StreamlinePath sline;
   int sides;
   int points;
   int id;
   float radius;

   StreamlinePath ComputeTubePath(Point seedPoint);
   void AllocatePointArray();
   void AllocateIndexArray();

   // auxilliary functions for finding the OpenGL graphics parameters
   void ComputeNormalArray();
   void ComputeVertexArray();
   void ComputeColorArray();
   void ComputeTextureArray(VectorField *stretch);
   void ComputeIndexArray();

// ArrayIndex is still used in DrawStreamtube()
   int ArrayIndex(int point, int side) { return( 3 * ( (point * sides) + point + side) );}

   bool UseTexture()    { return(texture != 0);}
   bool UseHelicity()   { return(helicityField != 0);}

   // objects for mapping values to properties of the tube
   //RadiusMap radiusMap;
   ColorMap *colorMap;
   Texture *texture;
   ScalarField *helicityField;

   // arrays that hold various info to render the tubes
   GLfloat *normalArray;
   GLfloat *vertexArray;
   GLfloat *colorArray;
   GLfloat *textureArray;
   GLuint *indices;
};

#endif
